<template>
  <view class="mm-wrap">
    <!-- 音/视频播放 -->
    <view class="mm-video-player">
      <view v-if="loading" class="video-loading">
        <u-loading mode="flower" :size="60" :color="globPrimaryColor" v-if="loading"></u-loading>
      </view>
      <div id="player-con"></div>
      <view class="video-image" v-if="!loading && sectionDataType == 2">
        <edu-image width="100%" :height="415" :src="detailsInfo.cover_url"></edu-image>
      </view>
    </view>

    <!-- 防挂机-弹窗 -->
    <prevent-popup
      v-if="detailsInfo.onhook_type == 1"
      ref="refPreventPopupVerify"
      :datas="playerData.onhook"
      @click="onVerifySuccess"
    ></prevent-popup>

    <!-- 防挂机-弹题 -->
    <prevent-question
      v-else-if="detailsInfo.onhook_type == 2"
      ref="refPreventQuestionVerify"
      :course_id="detailsInfo.id"
      :course_type="detailsInfo.course_type"
      @click="onVerifySuccess"
    ></prevent-question>

    <!-- 防挂机-人脸 -->
    <edu-face
      v-else-if="detailsInfo.onhook_type == 3"
      ref="refFaceVerify"
      @confirm="onFaceVerifyConfirm"
      @cancel="onFaceVerifyCancel"
    ></edu-face>
  </view>
</template>

<script>
import RateComponent from './components/RateComponent'
import PreviewVodComponent from './components/PreviewVodComponent'
import QualityComponent from './components/QualityComponent'
import BulletScreenComponent from './components/BulletScreenComponent'
import preventQuestion from '../preventQuestion'
import preventPopup from '../preventPopup'
import { mapState, mapGetters } from 'vuex'
import { uploadFile } from '@/utils/uploadFile.js'
const skinLayout = [
  {
    name: 'H5Loading',
    align: 'cc',
  },
  {
    name: 'controlBar',
    align: 'blabs',
    x: 0,
    y: 0,
    children: [
      { name: 'progress', align: 'blabs', x: 0, y: 44 },
      { name: 'playButton', align: 'tl', x: 15, y: 12 },
      { name: 'timeDisplay', align: 'tl', x: 10, y: 4 },
      {
        name: 'fullScreenButton',
        align: 'tr',
        x: 10,
        y: 12,
      },
    ],
  },
]
export default {
  props: {
    detailsInfo: {
      type: Object,
      default: () => {},
    },
    course_lock: {
      type: [String, Number],
      default: '',
    },
  },
  components: {
    preventQuestion,
    preventPopup,
  },
  data() {
    return {
      aplayer: {
        id: 'player-con', // 播放器外层容器的dom元素ID
        source: '', // 视频播放地址URL
        vid: '', // 媒体转码服务的媒体ID
        playauth: '', // 播放凭证
        width: '100%', // 播放器宽度
        height: uni.upx2px(415) + 'px',
        cover: '', // 播放器默认封面图片
        format: '', // 播放地址格式
        autoplay: false, // 播放器是否自动播放
        encryptType: 0, // 设置是否播放阿里云视频加密（私有加密）视频
        previewEndHtml: '#endPreviewTemplate', // 预览结束后显示在播放器中间的字符串。默认为空。
        previewBarHtml: '观看完整视频,请先购买课程', // 预览结束后显示在播放器左下角的字符串。默认为空。
        isLive: false,
        rePlay: false,
        playsinline: true,
        preload: true,
        controlBarVisibility: 'always',
        useH5Prism: true,
        marquee: ['', { fontSize: '16px', color: '#FF920A' }, 'random'], // 跑马灯
      },
      skinLayout: skinLayout,
      videoContext: null,
      continue: false, // 播放完成后是否继续播放下一首，需定义@next事件
      initialTime: 0, // 指定视频初始播放位置
      current: 0, // 当前进度(s)
      duration: 0, // 总时长(s)
      paused: true, // 是否处于暂停状态
      seek: false, // 是否处于拖动状态
      isFullScreen: false, // 是否处于全屏
      loading: true, //是否处于读取状态
      initialLoading: true, // 首次加载
      timer: null, // 计时器

      currentDuration: 0, // 记录学习时长

      previewEnd: false, // 试看状态
      previewDuration: 0, // 视频试看时长

      faceModalVisible: false, // 人脸验证弹出
      faceVerifyStart: false, // 人脸验证开始
      faceVerifyEnd: true, // 人脸验证结束
      faceVerifyNumber: 0, // 还需要验证次数
      faceIntervalTime: 0, //见时间间隔
      faceNextVerifyTime: 0, // 下一次验证时间
      faceSceneType: 2, // 场景
      faceSceneId: 0, // 验证id
      faceShootStatus: false, // 续播状态

      playerData: {}, // 播放数据
    }
  },
  computed: {
    ...mapGetters({
      globPrimaryColor: 'designSetting/getGlobThemeColor',
      userInfo: 'user/getUserInfo',
    }),
    ...mapState({
      getCurrentPlayItem: (state) => state.course.currentPlayItem,
    }),
    sectionDataType() {
      return this.getCurrentPlayItem.section_data.data_type || 1
    },
  },
  methods: {
    createDemoPlayer() {
      const script = document.createElement('script')
      const link = document.createElement('link')
      link.href =
        'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.0/skins/default/aliplayer-min.css'
      link.setAttribute('rel', 'stylesheet')
      script.src = 'https://g.alicdn.com/apsara-media-box/imp-web-player/2.20.0/aliplayer-h5-min.js'
      script.setAttribute('type', 'text/javascript')
      document.body.appendChild(script)
      document.body.appendChild(link)
      script.onload = () => {
        let props = {
          id: 'player-con', // 播放器外层容器的dom元素ID
          ...this.aplayer,
          skinLayout: this.skinLayout,
          components: [
            {
              name: 'RateComponent',
              type: RateComponent,
            },
            {
              name: 'PreviewVodComponent',
              type: PreviewVodComponent,
              args: [
                this.previewDuration,
                this.aplayer.previewEndHtml,
                this.aplayer.previewBarHtml,
              ],
            },
            {
              name: 'QualityComponent',
              type: QualityComponent,
            },
            {
              name: 'BulletScreenComponent',
              type: BulletScreenComponent,
              /** Descriptions of the scrolling text component parameters: text, style, bulletPosition
               * text: String 类型, 需要显示的文字
               * style: Object 类型, 类似 CSS 的写法, CSS 属性名用驼峰式的写法
               * bulletPosition:  可选参数, 默认为 'random': 随机位置(位置滚动一次后会随机改变); 另外可以设置成 'top'(顶部) 或 'bottom'(底部)
               */
              args: this.aplayer.marquee,
            },
          ],
        }
        this.videoContext = new window.Aliplayer(props)

        // 绑定事件，当 AliPlayer 初始化完成后，将编辑器实例通过自定义的 ready 事件交出去
        this.videoContext.on('ready', this.ready)
        this.videoContext.on('play', this.play)
        this.videoContext.on('pause', this.pause)
        this.videoContext.on('ended', this.ended)
        this.videoContext.on('timeupdate', this.timeupdate)
        this.videoContext.on('requestFullScreen', this.requestFullScreen)
        this.videoContext.on('cancelFullScreen', this.cancelFullScreen)
      }
    },
    /**
     * 加载完成
     */
    ready: function () {
      // dom插入版权声明
      const marqueeData = this.playerData.marquee
      if (!this.$u.test.empty(marqueeData) && marqueeData.copyright == 1) {
        let content = document.createElement('div')
        content.className = 'aliyun-component-copyright'
        let c = document.createElement('div')
        c.className = 'notice-content'
        let t = document.createElement('span')
        t.className = 'notice-text'
        t.innerHTML = marqueeData.copyright_content
        c.append(t)
        content.append(c)

        document.querySelector('#player-con').append(content)

        let rightBoxHtml = document.querySelector('#player-con .aliyun-component-copyright')
        let noticeHtml = document.querySelector(
          '#player-con .aliyun-component-copyright .notice-content'
        )
        noticeHtml.addEventListener('animationiteration', () => {
          rightBoxHtml.style.opacity = 0
          noticeHtml.style.animationPlayState = 'paused'
          setTimeout(() => {
            rightBoxHtml.style.opacity = 1
            noticeHtml.style.animationPlayState = 'running'
          }, marqueeData.frequency * 1000)
        })
      }

      setTimeout(() => {
        this.duration =
          this.videoContext.getDuration() || this.getCurrentPlayItem.section_data.duration
        this.isFullScreen = this.videoContext.fullscreenService.getIsFullScreen()
        if (this.initialLoading) {
          this.handleInitialTime(this.videoContext.getDuration())
          this.handleVerifyInit() // 人脸
          this.onPreviewDurationPay()
          this.initialLoading = false
        }
      }, 600)
    },
    /**
     * 播放视频
     */
    play: function () {
      this.paused = false
      clearInterval(this.timer)
      this.timer = setInterval(() => {
        this.currentDuration++
        if (this.currentDuration % 10 == 0) {
          this.handleAddLearning()
        }
      }, 1000)
      this.onVerifyTimeupdate()
    },
    /**
     * 暂停视频
     */
    pause: function () {
      this.paused = true
      clearInterval(this.timer)
      this.handleAddLearning()
    },
    /**
     * 当播放到末尾时
     */
    ended: function () {
      clearInterval(this.timer)
      this.handleAddLearning()

      // 顺序模式不能续播
      if (this.course_lock == 1) return

      // 继续播放
      if (this.continue) {
        //  人脸开关
        if (this.detailsInfo.onhook_type == 3) {
          if (this.isFullScreen) {
            this.videoContext.fullscreenService.cancelFullScreen()
            this.isFullScreen = false
          }
          this.handleModalConfirm()
          this.faceSceneType = 1
          this.faceSceneId = this.playerData.next_position.id
          this.faceShootStatus = true
        } else {
          this.next()
        }
      } else {
        this.paused = true
        this.current = 0
      }
    },
    /**
     * 播放进度变化时
     */
    timeupdate() {
      let currentTime = this.videoContext && this.videoContext.getCurrentTime()
      if (!this.seek) {
        this.current = Math.floor(currentTime)
      }
      this.onVerifyTimeupdate() // 人脸
      this.onPreviewDurationEnd(currentTime) // 处理试看
    },
    // 下一个
    next() {
      this.paused = true
      this.current = 0
      this.aplayer.autoplay = true
      this.$store.commit('course/setCurrentPlayItem', {
        ...this.getCurrentPlayItem,
        ...this.playerData.next_position,
      })
      if (this.videoContext) {
        this.videoContext.pause()
        this.videoContext.dispose() // 销毁
      }
      this.$emit('next')
    },
    // 当视频进入和退出全屏时
    requestFullScreen() {
      let rightBoxHtml = document.querySelector('#player-con .aliyun-component-copyright')
      this.isFullScreen = true
      rightBoxHtml.style.left = uni.upx2px(20) + 'px'
      rightBoxHtml.style.right = uni.upx2px(20) + 'px'
    },
    // 取消全屏事件
    cancelFullScreen() {
      let rightBoxHtml = document.querySelector('#player-con .aliyun-component-copyright')
      this.isFullScreen = false
      rightBoxHtml.style.left = uni.upx2px(100) + 'px'
      rightBoxHtml.style.right = uni.upx2px(190) + 'px'
    },
    // 获取播放地址
    getPlayerFile(data) {
      this.initialLoading = true
      this.playerData = data
      if (data.url_type == 1) {
        let arr = data.fileurl_array.reduce((obj, cur) => {
          obj[cur.definition] = cur.play_url
          return obj
        }, {})
        this.aplayer.source = JSON.stringify(arr)
      } else if (data.url_type === 2) {
        this.aplayer.source = data.fileurl_string
      }
      this.continue =
        !this.$u.test.empty(data.next_position) && !this.$u.test.empty(data.next_position.position)
      this.initialTime = this.getCurrentPlayItem.section_rate.current_time

      if (this.detailsInfo.onhook_type == 3) {
        this.faceSceneId = this.getCurrentPlayItem.id
      }

      this.current = this.initialTime
      this.handleAuditionTime() // 计算试听时长
      this.createDemoPlayer() // 创建
      if (this.videoContext) {
        this.videoContext.dispose() // 销毁
      }
      // 跑马灯
      let marqueeData = data.marquee
      if (!this.$u.test.empty(marqueeData) && this.sectionDataType == 1) {
        let name = ''
        let phone = ''
        if (marqueeData.username == 1) name = this.userInfo.nick_name
        if (marqueeData.phone == 1) phone = this.userInfo.phone
        let marqueeContent = name + phone
        if (marqueeContent) {
          this.aplayer.marquee = [
            marqueeContent,
            {
              fontSize: `${marqueeData.font_size}px`,
              color: this.$edu.test.hexToRgba(marqueeData.font_color, marqueeData.font_opacity),
            },
            'top',
            marqueeData.frequency,
          ]
        }
      }

      this.loading = false
    },
    // 计算试听时长
    handleAuditionTime() {
      this.previewEnd = false
      let buy = this.getCurrentPlayItem.is_buy
      if (this.$edu.test.isDef(buy) && buy == 0) {
        let audition = this.getCurrentPlayItem.audition || 0
        let duration = this.getCurrentPlayItem.section_data.duration || this.duration || 0
        this.previewDuration = Math.round(duration * (audition / 100))
      }
    },
    // 处理试看结束
    onPreviewDurationEnd(currentTime) {
      if (!this.previewEnd && this.previewDuration !== 0 && this.previewDuration < this.duration) {
        if (this.previewDuration < currentTime) {
          this.previewEnd = true
          this.videoContext.seek(this.previewDuration) // 跳转到某个时间点播放
          this.videoContext.pause()
          if (this.isFullScreen) {
            this.videoContext.fullscreenService.cancelFullScreen()
            this.isFullScreen = false
          }
        }
      }
    },
    // 试看购买
    onPreviewDurationPay() {
      // 绑定试看结束跳转按钮 START
      let previewDefaultEleBtn = document.querySelector(
        '.preview-vod-component .preview-default-btn'
      )
      let previewSectionEleBtn = document.querySelector(
        '.preview-vod-component .preview-section-btn'
      )
      const _this = this
      if (Number(this.getCurrentPlayItem.price) > 0) {
        previewSectionEleBtn.style.display = 'block'
      } else {
        previewSectionEleBtn.style.display = 'none'
      }

      previewDefaultEleBtn.onclick = function () {
        _this.$u.route({
          type: 'redirectTo',
          url: '/pageCourse/cart/course',
          params: {
            id: _this.getCurrentPlayItem.course_id,
          },
        })
      }
      previewSectionEleBtn.onclick = function () {
        _this.$u.route({
          type: 'redirectTo',
          url: '/pageCourse/cart/section',
          params: {
            id: _this.getCurrentPlayItem.id,
          },
        })
      }
      // 绑定试看结束跳转按钮 END
    },
    // 断点续播
    handleInitialTime(duration) {
      let buy = this.getCurrentPlayItem.is_buy
      if (this.$edu.test.isDef(buy) && buy == 0) return
      if (this.initialTime > duration - 5) {
        this.videoContext.seek(0) // // 跳转到某个时间点播放c
      } else {
        this.videoContext.seek(this.initialTime) // // 跳转到某个时间点播放
      }
    },
    /* 人脸 START */
    handleVerifyInit() {
      // 课时是否购买
      let buy = this.getCurrentPlayItem.is_buy
      if (this.$edu.test.isDef(buy) && this.getCurrentPlayItem.is_buy == 0) return

      // 是否是视频
      if (this.$edu.test.isDef(this.sectionDataType) && this.sectionDataType != 1) return

      // 是否开启验证
      if (this.detailsInfo.onhook_type == 0) return

      this.timer = null

      this.currentDuration = 0 // 当前播放时长

      this.faceSceneType = 2
      this.faceShootStatus = false
      this.faceVerifyEnd = false
      this.faceNextVerifyTime = 0

      if (this.detailsInfo.onhook_type == 1) {
        const onhookData = this.playerData.onhook
        this.faceVerifyNumber = onhookData.alert_max_number // 验证次数
        this.faceIntervalTime = onhookData.alert_time_interval * 60 // 时间间隔
      } else if (this.detailsInfo.onhook_type == 2) {
        const examData = this.playerData.onhook_exam
        this.faceVerifyNumber = examData.answer_max_number // 验证次数
        this.faceIntervalTime = examData.answer_time_interval * 60 // 时间间隔
      } else if (this.detailsInfo.onhook_type == 3) {
        const faceData = this.playerData.face_data
        this.faceVerifyNumber = faceData.need_verify_number // 验证次数
        this.faceIntervalTime = faceData.verify_timespan * 60 // 时间间隔
      }

      this.nextVerifyTime()
    },
    // 计算下一次验证时间
    nextVerifyTime() {
      if (this.faceVerifyNumber > 0) {
        let time = this.currentDuration + this.faceIntervalTime
        this.faceNextVerifyTime = time
      } else {
        this.faceVerifyEnd = true
      }
    },
    // 播放时弹出人脸
    onVerifyTimeupdate() {
      if (
        !this.faceVerifyEnd &&
        this.faceNextVerifyTime > 0 &&
        this.faceNextVerifyTime <= this.currentDuration
      ) {
        uni.$u.debounce(
          () => {
            if (this.isFullScreen) {
              this.videoContext.fullscreenService.cancelFullScreen()
              this.isFullScreen = false
            }
            if (this.detailsInfo.onhook_type == 1) {
              this.$refs.refPreventPopupVerify.onOpen()
            } else if (this.detailsInfo.onhook_type == 2) {
              this.$refs.refPreventQuestionVerify.onOpen()
            } else if (this.detailsInfo.onhook_type == 3) {
              this.handleModalConfirm()
            }
            this.videoContext.pause()
          },
          500,
          true
        )
      }
    },
    // 去验证人脸
    handleModalConfirm() {
      if (this.faceVerifyStart) return
      this.faceVerifyStart = true
      this.$refs.refFaceVerify.onFaceMessage()
    },
    // 人脸验证成功
    onVerifySuccess() {
      // 续播
      if (this.faceShootStatus) {
        this.next()
      } else {
        this.faceVerifyNumber-- // 还需要验证次数
        this.nextVerifyTime()
        this.videoContext.play()
      }
      this.faceVerifyStart = false
    },
    // 提交人脸验证
    onFaceVerifyConfirm(file) {
      uploadFile('/user/tencent/face/person/verify', file, {
        scene_key: 'course_section',
        scene_id: this.faceSceneId,
        scene_type: this.faceSceneType,
      })
        .then((res) => {
          this.$u.toast(res.msg)
          this.$refs.refFaceVerify.onClose()
          this.onVerifySuccess()
        })
        .catch((err) => {
          this.$u.toast(err.msg)
          this.$refs.refFaceVerify.resetPhoto()
        })
    },
    // 取消
    onFaceVerifyCancel() {
      this.faceVerifyStart = false
    },
    // 添加学习记录
    handleAddLearning() {
      let buy = this.getCurrentPlayItem.is_buy
      if (this.$edu.test.isDef(buy) && buy == 0) return
      this.$edu.api.createCourseRecord({
        course_id: this.getCurrentPlayItem.course_id,
        section_id: this.getCurrentPlayItem.id,
        current_time: this.current,
      })
    },
  },
  mounted() {
    // 暂停播放
    uni.$on('sectionPlayerPause', () => {
      if (this.videoContext) {
        this.videoContext.pause()
      }
    })
  },
  destroyed() {
    this.videoContext = null
  },
}
</script>

<style lang="scss" scoped>
/* 隐藏video 所有控件 */
::v-deep video::-webkit-media-controls {
  display: none !important;
}
::v-deep video::-webkit-media-controls-enclosure {
  display: none !important;
}
::v-deep.uni-video-progress-container {
  display: none;
}
.mm-wrap {
  height: 415rpx;
}

.mm-video-player {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #000000;
  .video-loading {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
    z-index: 100;
    background-color: #000000;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .video-image {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
  }

  ::v-deep .prism-player {
    .prism-time-display {
      color: #ffffff;
    }
  }

  ::v-deep .aliyun-component-copyright {
    position: absolute;
    top: 20rpx;
    left: 100rpx;
    right: 190rpx;
    z-index: 99;
    background: rgba(0, 0, 0, 0.2);
    overflow: hidden;
    display: flex;
    .notice-content {
      animation: aliyun-loop-animation 10s linear infinite both;
      text-align: right;
      padding-left: 100%;
      display: flex;
      flex-wrap: nowrap;
      box-sizing: border-box;
    }
    .notice-text {
      font-size: 24rpx;
      font-weight: 400;
      color: #ffffff;
      line-height: 52rpx;
      word-break: keep-all;
      white-space: nowrap;
    }
  }
}

@keyframes aliyun-loop-animation {
  0% {
    transform: translate3d(0, 0, 0);
  }

  100% {
    transform: translate3d(-100%, 0, 0);
  }
}
</style>
